home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * General matrix manipulation routines. *
- * *
- * Written by: Gershon Elber Ver 1.0, June 1988 *
- *****************************************************************************/
-
- #include <math.h>
- #include "irit_sm.h"
- #include "genmat.h"
-
- /*****************************************************************************
- * Routine to generate a 4*4 unit matrix: *
- *****************************************************************************/
- void MatGenUnitMat(MatrixType Mat)
- {
- int i, j;
-
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- if (i == j)
- Mat[i][j] = 1.0;
- else
- Mat[i][j] = 0.0;
- }
-
- /*****************************************************************************
- * Routine to generate a 4*4 matrix to translate in Tx, Ty, Tz amounts. *
- *****************************************************************************/
- void MatGenMatTrans(RealType Tx, RealType Ty, RealType Tz, MatrixType Mat)
- {
- MatGenUnitMat(Mat); /* Make it unit matrix. */
- Mat[3][0] = Tx;
- Mat[3][1] = Ty;
- Mat[3][2] = Tz;
- }
-
- /*****************************************************************************
- * Routine to generate a 4*4 matrix to Scale x, y, z in Sx, Sy, Sz amounts. *
- *****************************************************************************/
- void MatGenMatScale(RealType Sx, RealType Sy, RealType Sz, MatrixType Mat)
- {
- MatGenUnitMat(Mat); /* Make it unit matrix. */
- Mat[0][0] = Sx;
- Mat[1][1] = Sy;
- Mat[2][2] = Sz;
- }
-
- /*****************************************************************************
- * Routine to generate a 4*4 matrix to Rotate around X with angle of Teta. *
- * Note Teta must be given in radians. *
- *****************************************************************************/
- void MatGenMatRotX1(RealType Teta, MatrixType Mat)
- {
- RealType CTeta, STeta;
-
- CTeta = cos(Teta);
- STeta = sin(Teta);
- MatGenMatRotX(CTeta, STeta, Mat);
- }
-
- /*****************************************************************************
- * Routine to generate a 4*4 matrix to Rotate around X with angle of Teta. *
- *****************************************************************************/
- void MatGenMatRotX(RealType CosTeta, RealType SinTeta, MatrixType Mat)
- {
- MatGenUnitMat(Mat); /* Make it unit matrix. */
- Mat[1][1] = CosTeta;
- Mat[1][2] = SinTeta;
- Mat[2][1] = -SinTeta;
- Mat[2][2] = CosTeta;
- }
-
- /*****************************************************************************
- * Routine to generate a 4*4 matrix to Rotate around Y with angle of Teta. *
- * Note Teta must be given in radians. *
- *****************************************************************************/
- void MatGenMatRotY1(RealType Teta, MatrixType Mat)
- {
- RealType CTeta, STeta;
-
- CTeta = cos(Teta);
- STeta = sin(Teta);
- MatGenMatRotY(CTeta, STeta, Mat);
- }
-
- /*****************************************************************************
- * Routine to generate a 4*4 matrix to Rotate around Y with angle of Teta. *
- *****************************************************************************/
- void MatGenMatRotY(RealType CosTeta, RealType SinTeta, MatrixType Mat)
- {
- MatGenUnitMat(Mat); /* Make it unit matrix. */
- Mat[0][0] = CosTeta;
- Mat[0][2] = -SinTeta;
- Mat[2][0] = SinTeta;
- Mat[2][2] = CosTeta;
- }
-
- /*****************************************************************************
- * Routine to generate a 4*4 matrix to Rotate around Z with angle of Teta. *
- * Note Teta must be given in radians. *
- *****************************************************************************/
- void MatGenMatRotZ1(RealType Teta, MatrixType Mat)
- {
- RealType CTeta, STeta;
-
- CTeta = cos(Teta);
- STeta = sin(Teta);
- MatGenMatRotZ(CTeta, STeta, Mat);
- }
-
- /*****************************************************************************
- * Routine to generate a 4*4 matrix to Rotate around Z with angle of Teta. *
- *****************************************************************************/
- void MatGenMatRotZ(RealType CosTeta, RealType SinTeta, MatrixType Mat)
- {
- MatGenUnitMat(Mat); /* Make it unit matrix. */
- Mat[0][0] = CosTeta;
- Mat[0][1] = SinTeta;
- Mat[1][0] = -SinTeta;
- Mat[1][1] = CosTeta;
- }
-
- /*****************************************************************************
- * Routine to multiply 2 4by4 matrices: *
- * Note MatRes might be one of Mat1 or Mat2 - it is only updated in the end! *
- *****************************************************************************/
- void MatMultTwo4by4(MatrixType MatRes, MatrixType Mat1, MatrixType Mat2)
- {
- int i, j, k;
- MatrixType MatResTemp;
-
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++) {
- MatResTemp[i][j] = 0;
- for (k = 0; k < 4; k++)
- MatResTemp[i][j] += Mat1[i][k] * Mat2[k][j];
- }
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- MatRes[i][j] = MatResTemp[i][j];
- }
-
- /*****************************************************************************
- * Routine to add 2 4by4 matrices: *
- * Note MatRes might be one of Mat1 or Mat2. *
- *****************************************************************************/
- void MatAddTwo4by4(MatrixType MatRes, MatrixType Mat1, MatrixType Mat2)
- {
- int i, j;
-
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- MatRes[i][j] = Mat1[i][j] + Mat2[i][j];
- }
-
- /*****************************************************************************
- * Routine to subtract 2 4by4 matrices: *
- * Note MatRes might be one of Mat1 or Mat2. *
- *****************************************************************************/
- void MatSubTwo4by4(MatrixType MatRes, MatrixType Mat1, MatrixType Mat2)
- {
- int i, j;
-
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- MatRes[i][j] = Mat1[i][j] - Mat2[i][j];
- }
-
- /*****************************************************************************
- * Routine to scale a 4by4 matrix by constant: *
- * Note MatRes might be Mat. *
- *****************************************************************************/
- void MatScale4by4(MatrixType MatRes, MatrixType Mat, RealType *Scale)
- {
- int i, j;
-
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- MatRes[i][j] = Mat[i][j] * (*Scale);
- }
-
- /*****************************************************************************
- * Routine to multiply Vector by 4by4 matrix: *
- * The Vector has only 3 components (X, Y, Z) and it is assumed that W = 1 *
- * Note VRes might be Vec as it is only updated in the end. *
- *****************************************************************************/
- void MatMultVecby4by4(VectorType VRes, VectorType Vec, MatrixType Mat)
- {
- int i, j;
- RealType
- CalcW = Mat[3][3];
- VectorType VTemp;
-
- for (i = 0; i < 3; i++) {
- VTemp[i] = Mat[3][i]; /* Initiate it with the weight factor. */
- for (j = 0; j < 3; j++)
- VTemp[i] += Vec[j] * Mat[j][i];
- }
-
- for (i = 0; i < 3; i++)
- CalcW += Vec[i] * Mat[i][3];
- if (CalcW == 0)
- CalcW = 1 / INFINITY;
-
- for (i = 0; i < 3; i++)
- VRes[i] = VTemp[i] / CalcW;
- }
-
- /*****************************************************************************
- * Routine to multiply Vector by 4by4 matrix: *
- * The Vector has 4 components (X, Y, Z, W). *
- * Note VRes might be Vec as it is only updated in the end. *
- *****************************************************************************/
- void MatMultWVecby4by4(RealType VRes[4], RealType Vec[4], MatrixType Mat)
- {
- int i, j;
- RealType VTemp[4];
-
- for (i = 0; i < 4; i++) {
- VTemp[i] = 0.0;
- for (j = 0; j < 4; j++)
- VTemp[i] += Vec[j] * Mat[j][i];
- }
-
- for (i = 0; i < 4; i++)
- VRes[i] = VTemp[i];
- }
-
- /*****************************************************************************
- * Procedure to calculate the INVERSE of a given matrix M which is not *
- * modified. The matrix is assumed to be 4 by 4 (transformation matrix). *
- * Return TRUE if inverted matrix (InvM) do exists. *
- *****************************************************************************/
- int MatInverseMatrix(MatrixType M, MatrixType InvM)
- {
- MatrixType A;
- int i, j, k;
- RealType V;
-
- MAT_COPY(A, M); /* Prepare temporary copy of M in A. */
- MatGenUnitMat(InvM); /* Make it unit matrix. */
-
- for (i = 0; i < 4; i++) {
- V = A[i][i]; /* Find the new pivot. */
- k = i;
- for (j = i + 1; j < 4; j++)
- if (ABS(A[j][i]) > ABS(V)) {
- /* Find maximum on col i, row i+1..n */
- V = A[j][i];
- k = j;
- }
- j = k;
-
- if (i != j)
- for (k = 0; k < 4; k++) {
- SWAP(RealType, A[i][k], A[j][k]);
- SWAP(RealType, InvM[i][k], InvM[j][k]);
- }
-
- for (j = i + 1; j < 4; j++) { /* Eliminate col i from row i+1..n. */
- V = A[j][i] / A[i][i];
- for (k = 0; k < 4; k++) {
- A[j][k] -= V * A[i][k];
- InvM[j][k] -= V * InvM[i][k];
- }
- }
- }
-
- for (i = 3; i >= 0; i--) { /* Back Substitution. */
- if (A[i][i] == 0)
- return FALSE; /* Error. */
-
- for (j = 0; j < i; j++) { /* Eliminate col i from row 1..i-1. */
- V = A[j][i] / A[i][i];
- for (k = 0; k < 4; k++) {
- /* A[j][k] -= V * A[i][k]; */
- InvM[j][k] -= V * InvM[i][k];
- }
- }
- }
-
- for (i = 0; i < 4; i++) /* Normalize the inverse Matrix. */
- for (j = 0; j < 4; j++)
- InvM[i][j] /= A[i][i];
-
- return TRUE;
- }
-